package com.da.demo;

import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @Description: TODO()
 * @Author da
 * @Date 2022/2/28 上午 11:33
 */
public class Main
{
    //    数据库链接
    static Connection connection = null;
    static String catalog = "";
    static DatabaseMetaData metaData = null;

    public static void main(String[] args) throws Exception
    {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/main/resources/mysql.properties"));
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");
        String driver = properties.getProperty("driver");
//        加载数据库驱动
        Class.forName(driver);
//        链接数据库
        connection = DriverManager.getConnection(url, username, password);
//        获取当前链接的数据库名字
        catalog = connection.getCatalog();
//        创建DatabaseMetaData对象
        metaData = connection.getMetaData();
//        获取当前数据库中的所有表的信息
        ResultSet tables = metaData.getTables(catalog, null, null, null);
//        处理获取的结果集,获取当前数据库中所有的表
        getTables(tables).forEach(i ->
        {
            String code = i.createJavaCode();
//            用属性生成的代码替换掉%body%
            code = code.replace("%body%", "\n" + createColumnCode(i.getTableName()) + "\n");
            writeCode(i.getTableName(), code);
        });
        //     通过表名生成对应的java文件内容

    }

    //    写入代码到指定文件
    private static void writeCode(String table, String code)
    {
        try
        {
//        指定保存文件保存的位置(启动类的包名+po)
            String savePackage = Main.class.getPackage().getName() + ".po";
            Path path = Paths.get("src/main/java/" + savePackage.replaceAll("\\.", "/"));
            Files.createDirectories(path);
//            处理Data类型的引入
            if (code.contains("Date"))
            {
                code = "import java.util.Date;\n\n" + code;
            }
//            指定包名
            code = "package " + savePackage + ";\n\n" + code;
//            保存的文件名字 表名首字母大写.java
            String fileName = StringUtil.tableNameToClassName(table) + ".java";
//            写入文件
            Files.write(path.resolve(fileName), code.getBytes(StandardCharsets.UTF_8));
            System.out.println("生成" + table + "的实体类成功!");
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    //  生成当前表属性字段的代码
    private static String createColumnCode(String table)
    {
//        获取对应的所有属性信息,生成对应的代码
        return getTableColumns(table)
                .stream()
                .map(ColumnInfo::createJavaCode)
                .collect(Collectors.joining("\n\n"));
    }


    //    获取当前表对应的所有属性
    private static List<ColumnInfo> getTableColumns(String table)
    {
        List<ColumnInfo> infos = new ArrayList<>();
        try
        {
//        获取当前表的行属性
            ResultSet rs = metaData.getColumns(catalog, null, table, null);
            while (rs.next())
            {
                ColumnInfo info = new ColumnInfo();
                info.setColumnName(rs.getString("COLUMN_NAME"));
                info.setTypeName(rs.getString("TYPE_NAME"));
                info.setRemarks(rs.getString("REMARKS"));
                info.setOrdinalPosition(rs.getInt("ORDINAL_POSITION"));
                infos.add(info);
            }

        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return infos;
    }


    //    获取当前数据库中所有的表
    private static List<TableInfo> getTables(ResultSet rs) throws SQLException
    {
//        保存所有的表信息
        List<TableInfo> infos = new ArrayList<>();
        while (rs.next())
        {
            TableInfo info = new TableInfo();
//            获取表名
            info.setTableName(rs.getString("TABLE_NAME"));
//            获取备注
            info.setRemarks(rs.getString("REMARKS"));
            infos.add(info);
        }
        return infos;
    }


}
